/**
 * bomb.js
 *
 * 操作方法
 *  移動：異動先をタッチする
 *  爆弾設置：自分をタッチする
 **/

const GAME_WIDTH = 320;
const GAME_HEIGHT = 320;

const MAP_TIP_SIZE = 16;
const CHARA_SIZE = 32;

const IMG_START        = "images/start.png";
const IMG_END          = "images/end.png";
const IMG_MAP          = "images/map1.png";
const IMG_CHAR         = "images/chara0.png";
const IMG_EMEMY        = "images/chara6.png";
const IMG_ICON         = "images/icon0.png";
const IMG_BOMB_EFFECT  = "images/effect0.png";

const MOVE_UP = 1;
const MOVE_RIGHT = 2;
const MOVE_DOWN = 3;
const MOVE_LEFT = 4;

const TEST_MAP = [
[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7],
[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,7],
[7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,7],
[7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,7],
[7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,7],
[7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,1,7,7,1,7],
[7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7],
[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7],
];

const TEST_MAP_COLLISION = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0],
[0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0],
[0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0],
[0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0],
[0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
];


function getScale() {
  return Math.min($(window).width(), $(window).height())/Math.min(GAME_WIDTH, GAME_HEIGHT);
}

/**
 * ゲームタイトル画面
 **/
function createTitileScene() {
  const IMG_START_WIDTH = 236;
  const IMG_START_HEIGHT = 48
  var scene = new Scene();
  var sprite = new Sprite(IMG_START_WIDTH, IMG_START_HEIGHT);
  sprite.x = GAME_WIDTH / 2 - IMG_START_WIDTH / 2;
  sprite.y = GAME_HEIGHT / 2 - IMG_START_HEIGHT / 2;
  sprite.image = game.assets[IMG_START];
  scene.addChild(sprite);
  var label = new Label();
  label.text = "bomb.js"
  scene.addChild(label);
  sprite.addEventListener('touchstart', function() {
    console.log('game start touch');
    game.pushScene(createGameScene());
  });
  return scene;
}

/**
 * ゲームオーバーの画面
 **/
function createGameOverScene() {
  const IMG_END_WIDTH = 189;
  const IMG_END_HEIGHT = 97
  var scene = new Scene();
  var sprite = new Sprite(IMG_END_WIDTH, IMG_END_HEIGHT);
  sprite.x = GAME_WIDTH / 2 - IMG_END_WIDTH / 2;
  sprite.y = GAME_HEIGHT / 2 - IMG_END_HEIGHT / 2;
  sprite.image = game.assets[IMG_END];
  scene.addChild(sprite);
  sprite.addEventListener('touchstart', function() {
    game.pushScene(createTitleScene());
  });
  return scene;
}

/**
 * ゲーム中の画面
 **/
function createGameScene() {
  var scene = new Scene();
  scene.backgroundColor = 'red';
  map = new Map(MAP_TIP_SIZE,MAP_TIP_SIZE);
  map.image = game.assets[IMG_MAP];
  map.loadData(TEST_MAP);
  map.collisionData = TEST_MAP_COLLISION;
  scene.addChild(map);

  player = new Human();
  scene.addChild(player);

  enemies = new Array();
  for(var i = 0; i < 10; i++) {
    enemies[i] = new Enemy();
    scene.addChild(enemies[i]);
  }

  scene.addEventListener('touchstart', function(e) {
    player.moveRoot(e.localX,e.localY);
  });
  return scene;
}

$(document).ready(function() {
  enchant();
  game = new Game(GAME_WIDTH, GAME_HEIGHT);
  game.preload(
    IMG_START, IMG_END, IMG_MAP, IMG_CHAR,
    IMG_EMEMY, IMG_BOMB_EFFECT, IMG_ICON
  );

  game.onload = function () {
    game.pushScene(createTitileScene());
  }
  game.scale = getScale();
  game.start();
});

/**
 * Human class
 * プレイヤー定義クラス。
 **/
var Human = enchant.Class.create(enchant.Sprite, {
  /**
   * コンストラクタ
   **/
  initialize:function() {
    enchant.Sprite.call(this, CHARA_SIZE, CHARA_SIZE);
    this.mapX = 2;
    this.mapY = 2;
    this.x = this.mapX * MAP_TIP_SIZE - (CHARA_SIZE/4);
    this.y = this.mapY * MAP_TIP_SIZE - (CHARA_SIZE/2);
    this.frame = [1, 0, 1, 2];
    this.image = game.assets[IMG_CHAR];
    this.dx = 0;
    this.dy = 0;
    this.mRoot = new Array();
    this.addEventListener('enterframe', function () {
      this.move();
    });
    this.addEventListener('touchstart', function(){
      var bomb = new Bomb(this.x, this.y);
      this.scene.addChild(bomb);
    });
  },

  /**
   * 移動する
   **/
  move: function() {
    if(this.mRoot.length > 0) {
      this.moveDirection();
    }
  },

  /**
   * 移動する方向を決める
   **/
  moveDirection: function() {
      switch(this.mRoot.pop()) {
        case MOVE_UP:
        this.tl.then(function(){this.frame = [28, 27, 28, 29];});
        this.tl.moveBy(0, -MAP_TIP_SIZE, 10);
        this.mapY -= 1;
  	    break;
  	  case MOVE_RIGHT:
        this.tl.then(function(){this.frame = [19, 18, 19, 20];});
        this.tl.moveBy(MAP_TIP_SIZE,0, 10);
        this.mapX += 1;
  	    break;
  	  case MOVE_DOWN:
        this.tl.then(function(){this.frame = [1, 0, 1, 2];});
        this.tl.moveBy(0,MAP_TIP_SIZE, 10);
        this.mapY += 1;
  	    break;
  	  case MOVE_LEFT:
        this.tl.then(function(){this.frame = [10, 9, 10, 11];});
        this.tl.moveBy(-MAP_TIP_SIZE, 0, 10);
        this.mapX -= 1;
  	    break;
    }
  },

  /**
   * 経路探索
   **/
  moveRoot: function(touch_x,touch_y) {
  	if(this.mRoot.length != 0)
  	  return;

    var ax =  Math.floor(touch_x / MAP_TIP_SIZE);
    var ay =  Math.floor(touch_y / MAP_TIP_SIZE);
    if (map.collisionData[ay][ax] == 0) {
      return;
    }
    var rootmap = new Array(map.collisionData.length);
    for(i=0;i<rootmap.length;i++) {
       rootmap[i] = new Array(map.collisionData[0].length);
       for(j=0;j<rootmap[i].length;j++) {
         rootmap[i][j] = Number.MAX_VALUE;
       }
    }
    var moveroot = new Array();
    moveroot[0] = -1;
    moveroot = this.moveRootSub(moveroot,rootmap,ax,ay,1);
    if(moveroot) {
      this.mRoot = moveroot;
      this.mRoot.splice(0,1);
      //console.log(this.mRoot);
    }
  },
  /**
   * 経路探索サブクラス
   **/
  moveRootSub: function(moveroot,rootmap,sx,sy,n) {
    if(rootmap[this.mapY][this.mapX] <= n) {
      return null;
    }
    rootmap[sy][sx] = n;

    if(sx == this.mapX && sy == this.mapY) {
      moveroot[0] = 0;
      moveroot.splice(n,moveroot.length-n);
      return moveroot;
    }

	var tempRoot;
    var retRoot;

    if(map.collisionData[sy-1][sx] == 1 && rootmap[sy-1][sx] > n) {
      moveroot[n] = MOVE_DOWN;
      tempRoot = this.moveRootSub(moveroot,rootmap,sx,sy-1,n+1);
      if(tempRoot) {
        retRoot = tempRoot.slice(0);
      }
    }
    if(map.collisionData[sy][sx+1] == 1 && rootmap[sy][sx+1] > n) {
      moveroot[n] = MOVE_LEFT;
      tempRoot = this.moveRootSub(moveroot,rootmap,sx+1,sy,n+1);
      if(tempRoot) {
        retRoot = tempRoot.slice(0);
      }
    }
    if(map.collisionData[sy+1][sx] == 1 && rootmap[sy+1][sx] > n) {
      moveroot[n] = MOVE_UP;
      tempRoot = this.moveRootSub(moveroot,rootmap,sx,sy+1,n+1);
      if(tempRoot) {
        retRoot = tempRoot.slice(0);
      }
    }
    if(map.collisionData[sy][sx-1] == 1 && rootmap[sy][sx-1] > n) {
      moveroot[n] = MOVE_RIGHT;
      tempRoot = this.moveRootSub(moveroot,rootmap,sx-1,sy,n+1);
      if(tempRoot) {
        retRoot = tempRoot.slice(0);
      }
    }

    return (retRoot && retRoot.length) ? retRoot : null;
  },

});

/**
 * Enemy class
 * 敵定義クラス。
 **/
var Enemy = enchant.Class.create(enchant.Sprite, {

  /**
   * コンストラクタ
   **/
  initialize: function() {
    enchant.Sprite.call(this, CHARA_SIZE, CHARA_SIZE);
    while(!map.hitTest(this.x, this.y)) {
      this.x = Math.floor(Math.random() * 10) * MAP_TIP_SIZE;
      this.y = Math.floor(Math.random() * 10) * MAP_TIP_SIZE;
    }
    this.image = game.assets[IMG_EMEMY];
    this.frame = [3,4,5];
    this.addEventListener('enterframe', function () {
      this.move();
    });
    this.decideDirection();
  },

  /**
   * 移動する
   **/
  move: function() {

    this.x += this.deltaX;
    this.y += this.deltaY;

    if (!map.hitTest(this.x + this.deltaX + CHARA_SIZE/2, this.y + this.deltaY + CHARA_SIZE/2)) {
      this.decideDirection();
    }
  },

  /**
   * 移動方向を決定する
   **/
  decideDirection: function() {
    while(!map.hitTest(this.x + this.deltaX + CHARA_SIZE/2, this.y + this.deltaY + CHARA_SIZE/2)) {
      this.deltaX = Math.floor(Math.random() * 3) - 1;
      this.deltaY = this.deltaX == 0 ? (Math.random() < 0.5 ? -1 : 1): 0;
    }
  }
});

/**
 * Bomb class
 * 爆弾定義クラス。
 **/
var Bomb = enchant.Class.create(enchant.Sprite, {

  /**
   * コンストラクタ
   **/
  initialize: function(x, y) {
    enchant.Sprite.call(this, MAP_TIP_SIZE, MAP_TIP_SIZE);
    this.x = (Math.floor(x/MAP_TIP_SIZE)+1) * MAP_TIP_SIZE;
    this.y = (Math.floor(y/MAP_TIP_SIZE)+1) * MAP_TIP_SIZE;
    this.image = game.assets[IMG_ICON];
    this.frame = [24];
    this.bombTimer = 100;
    this.addEventListener('enterframe', function () {
      this.bombTimer -= 1;
      if (this.bombTimer == 0) {
        this.bombEffect = new Sprite(16, 16);
        this.bombEffect.x = this.x;
        this.bombEffect.y = this.y;
        this.bombEffect.image = game.assets[IMG_BOMB_EFFECT];
        this.bombEffect.frame = [0,1,2,3,4, null];
        this.scene.addChild(this.bombEffect);
      }
      if (this.bombEffect && (this.bombEffect.age > 6)) {
        this.scene.removeChild(this.bombEffect);
        this.scene.removeChild(this);
        this.bombEffect = null;
      }
    });
  },
});
